//! 内存工具
//! 
//! 提供内存相关的工具函数和监控功能

use std::mem;

/// 内存工具类
pub struct MemoryUtils;

impl MemoryUtils {
    /// 获取类型的大小（字节）
    pub fn size_of<T>() -> usize {
        mem::size_of::<T>()
    }

    /// 获取值的大小（字节）
    pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
        mem::size_of_val(val)
    }

    /// 格式化字节数为人类可读格式
    pub fn format_bytes(bytes: usize) -> String {
        const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
        const THRESHOLD: f64 = 1024.0;

        if bytes == 0 {
            return "0 B".to_string();
        }

        let mut size = bytes as f64;
        let mut unit_index = 0;

        while size >= THRESHOLD && unit_index < UNITS.len() - 1 {
            size /= THRESHOLD;
            unit_index += 1;
        }

        if unit_index == 0 {
            format!("{} {}", bytes, UNITS[unit_index])
        } else {
            format!("{:.2} {}", size, UNITS[unit_index])
        }
    }

    /// 计算对齐后的大小
    pub fn align_to(size: usize, alignment: usize) -> usize {
        (size + alignment - 1) & !(alignment - 1)
    }

    /// 检查指针是否对齐
    pub fn is_aligned<T>(ptr: *const T, alignment: usize) -> bool {
        (ptr as usize) % alignment == 0
    }
}

/// 内存池简单实现（用于小对象分配优化）
pub struct MemoryPool<T> {
    pool: Vec<T>,
    free_indices: Vec<usize>,
}

impl<T> MemoryPool<T> {
    /// 创建新的内存池
    pub fn new() -> Self {
        Self {
            pool: Vec::new(),
            free_indices: Vec::new(),
        }
    }

    /// 预分配指定数量的对象
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            pool: Vec::with_capacity(capacity),
            free_indices: Vec::new(),
        }
    }

    /// 从池中获取对象的索引，如果池为空则扩展
    pub fn allocate(&mut self, item: T) -> usize {
        if let Some(index) = self.free_indices.pop() {
            self.pool[index] = item;
            index
        } else {
            let index = self.pool.len();
            self.pool.push(item);
            index
        }
    }

    /// 释放对象回池中
    pub fn deallocate(&mut self, index: usize) -> Option<T> {
        if index < self.pool.len() {
            self.free_indices.push(index);
            // 注意：这里不实际移除对象，只是标记为可用
            // 实际实现中可能需要更复杂的管理
            None
        } else {
            None
        }
    }

    /// 获取对象的引用
    pub fn get(&self, index: usize) -> Option<&T> {
        self.pool.get(index)
    }

    /// 获取对象的可变引用
    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
        self.pool.get_mut(index)
    }

    /// 获取池的大小
    pub fn size(&self) -> usize {
        self.pool.len()
    }

    /// 获取可用对象数量
    pub fn available(&self) -> usize {
        self.free_indices.len()
    }

    /// 获取已使用对象数量
    pub fn used(&self) -> usize {
        self.pool.len() - self.free_indices.len()
    }
}

impl<T> Default for MemoryPool<T> {
    fn default() -> Self {
        Self::new()
    }
}

/// 内存统计信息
#[derive(Debug, Clone)]
pub struct MemoryStats {
    /// 总分配字节数
    pub total_allocated: usize,
    /// 当前使用字节数
    pub current_used: usize,
    /// 分配次数
    pub allocation_count: usize,
    /// 释放次数
    pub deallocation_count: usize,
}

impl MemoryStats {
    /// 创建新的内存统计
    pub fn new() -> Self {
        Self {
            total_allocated: 0,
            current_used: 0,
            allocation_count: 0,
            deallocation_count: 0,
        }
    }

    /// 记录分配
    pub fn record_allocation(&mut self, size: usize) {
        self.total_allocated += size;
        self.current_used += size;
        self.allocation_count += 1;
    }

    /// 记录释放
    pub fn record_deallocation(&mut self, size: usize) {
        self.current_used = self.current_used.saturating_sub(size);
        self.deallocation_count += 1;
    }

    /// 获取平均分配大小
    pub fn average_allocation_size(&self) -> f64 {
        if self.allocation_count == 0 {
            0.0
        } else {
            self.total_allocated as f64 / self.allocation_count as f64
        }
    }

    /// 获取内存利用率
    pub fn utilization_rate(&self) -> f64 {
        if self.total_allocated == 0 {
            0.0
        } else {
            self.current_used as f64 / self.total_allocated as f64
        }
    }
}

impl Default for MemoryStats {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_format_bytes() {
        assert_eq!(MemoryUtils::format_bytes(0), "0 B");
        assert_eq!(MemoryUtils::format_bytes(512), "512 B");
        assert_eq!(MemoryUtils::format_bytes(1024), "1.00 KB");
        assert_eq!(MemoryUtils::format_bytes(1536), "1.50 KB");
        assert_eq!(MemoryUtils::format_bytes(1048576), "1.00 MB");
    }

    #[test]
    fn test_align_to() {
        assert_eq!(MemoryUtils::align_to(7, 8), 8);
        assert_eq!(MemoryUtils::align_to(8, 8), 8);
        assert_eq!(MemoryUtils::align_to(9, 8), 16);
        assert_eq!(MemoryUtils::align_to(15, 16), 16);
        assert_eq!(MemoryUtils::align_to(17, 16), 32);
    }

    #[test]
    fn test_memory_pool() {
        let mut pool = MemoryPool::new();
        
        let index1 = pool.allocate(String::from("hello"));
        let index2 = pool.allocate(String::from("world"));
        
        assert_eq!(pool.size(), 2);
        assert_eq!(pool.used(), 2);
        assert_eq!(pool.available(), 0);
        
        assert_eq!(pool.get(index1).unwrap(), "hello");
        assert_eq!(pool.get(index2).unwrap(), "world");
        
        pool.deallocate(index1);
        assert_eq!(pool.used(), 1);
        assert_eq!(pool.available(), 1);
    }

    #[test]
    fn test_memory_stats() {
        let mut stats = MemoryStats::new();
        
        stats.record_allocation(1024);
        stats.record_allocation(512);
        
        assert_eq!(stats.total_allocated, 1536);
        assert_eq!(stats.current_used, 1536);
        assert_eq!(stats.allocation_count, 2);
        assert_eq!(stats.average_allocation_size(), 768.0);
        
        stats.record_deallocation(512);
        assert_eq!(stats.current_used, 1024);
        assert_eq!(stats.deallocation_count, 1);
    }
}